﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using DotNetApp.Toolkit.Services;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using Microsoft.Phone.Tasks;
using WinSource.Model;
using WinSource.Services;

namespace WinSource.ViewModel
{
    public class IsRefreshingArticlesPropertyChangedMessage
    {
    }

    public class MainViewModel : ViewModelBase
    {
        #region Fields

        private readonly DataService _dataService;
        private readonly NavigationService _navigationService;

        #endregion

        #region Constructor

        public MainViewModel(DataService dataService, NavigationService navigationService)
        {
            if (!DesignerProperties.IsInDesignTool)
            {
                _dataService = dataService;
                _navigationService = navigationService;

                LoadedCommand = new RelayCommand(RefreshData);
                RefreshCommand = new RelayCommand(ForceRefreshData);
                ShowSavedArticlesCommand = new RelayCommand(ShowSavedArticles);
                ShowFacebookPageCommand = new RelayCommand(ShowFacebookPage);
                ShowTwitterPageCommand = new RelayCommand(ShowTwitterPage);
                ShowSettingsCommand = new RelayCommand(ShowSettings);
                ShowAboutCommand = new RelayCommand(ShowAbout);
                ReadArticleCommand = new RelayCommand<Article>(ReadArticle);
                ReadCurrentArticleCommand = new RelayCommand(ReadCurrentArticle);
                ViewCurrentVideoCommand = new RelayCommand(ViewCurrentVideo);
                ShowWriterCommand = new RelayCommand<Writer>(ShowWriter);
                SendTipCommand = new RelayCommand(SendTip);

                IsRefreshingArticles = _dataService.IsRefreshingArticles;
                IsRefreshingVideos = _dataService.IsRefreshingVideos;

                HasInternet = true;

                _dataService.OnDataRefreshed += DataServiceOnDataRefreshed;

                UpdateArticles();
                UpdateVideos();
            }
        }

        #endregion

        #region Properties

        public bool HasInternet { get; private set; }
        public bool IsCachedModeMessageDisplayed { get; set; }
        public bool IsRefreshingArticles { get; set; }
        public Article FeatureArticle1 { get; private set; }
        public Article FeatureArticle2 { get; private set; }
        public Article FeatureArticle3 { get; private set; }
        public List<Article> Articles { get; set; }
        public IEnumerable<GroupArticleByDate> ArticlesByDate { get; private set; }
        public Article CurrentArticle { get; set; }
        public bool IsRefreshingVideos { get; private set; }
        public List<Video> Videos { get; set; }
        public Video CurrentVideo { get; set; }

        public Writer WriterJoe
        {
            get { return _dataService.WriterJoe; }
        }

        public Writer WriterAshley
        {
            get { return _dataService.WriterAshley; }
        }
        
        public RelayCommand LoadedCommand { get; private set; }
        public RelayCommand RefreshCommand { get; private set; }
        public RelayCommand ShowSavedArticlesCommand { get; private set; }
        public RelayCommand ShowFacebookPageCommand { get; private set; }
        public RelayCommand ShowTwitterPageCommand { get; private set; }
        public RelayCommand ShowSettingsCommand { get; private set; }
        public RelayCommand ShowAboutCommand { get; private set; }
        public RelayCommand<Article> ReadArticleCommand { get; private set; }
        public RelayCommand ReadCurrentArticleCommand { get; private set; }
        public RelayCommand ViewCurrentVideoCommand { get; private set; }
        public RelayCommand<Writer> ShowWriterCommand { get; private set; }
        public RelayCommand SendTipCommand { get; private set; }

        #endregion

        #region Event Handlers

        private void DataServiceOnDataRefreshed(object sender, DataRefreshedEventArgs dataRefreshedEventArgs)
        {
            switch (dataRefreshedEventArgs.DataType)
            {
                case DataType.Articles:
                    UpdateArticles();

                    HasInternet = dataRefreshedEventArgs.IsSuccess;

                    if (!dataRefreshedEventArgs.IsSuccess && !IsCachedModeMessageDisplayed)
                    {
                        IsCachedModeMessageDisplayed = true;

                        if (Articles != null)
                        {
                            MessageBox.Show("You currently have no Internet connection.\nYou can still view the previous information.", "Cached mode", MessageBoxButton.OK);
                        }
                        else
                        {
                            MessageBox.Show("When launching the application for the first time, the Internet is required.\n\nRestart the application when you'll have an Internet connection.",
                                            "Internet connection missing", MessageBoxButton.OK);
                        }
                    }

                    IsRefreshingArticles = false;

                    Messenger.Default.Send(new IsRefreshingArticlesPropertyChangedMessage());
                    break;

                case DataType.Videos:
                    if (dataRefreshedEventArgs.IsSuccess)
                    {
                        UpdateVideos();
                    }

                    IsRefreshingVideos = false;
                    break;
            }
        }

        #endregion

        #region Command

        private void RefreshData()
        {
            if (_dataService.CanRefreshData())
            {
                IsRefreshingArticles = true;

                _dataService.RefreshData(false);
            }
        }

        private void ForceRefreshData()
        {
            IsRefreshingArticles = true;

            Messenger.Default.Send(new IsRefreshingArticlesPropertyChangedMessage());

            _dataService.RefreshData(true);
        }

        private void ShowSavedArticles()
        {
            _navigationService.NavigateTo(new Uri("/Views/SavedArticlesPage.xaml", UriKind.Relative));
        }

        private void ShowFacebookPage()
        {
            try
            {
                WebBrowserTask webBrowserTask = new WebBrowserTask {Uri = new Uri("https://www.facebook.com/WinSource1")};
                webBrowserTask.Show();
            }
            catch
            {
            }
        }

        private void ShowTwitterPage()
        {
            try
            {
                WebBrowserTask webBrowserTask = new WebBrowserTask { Uri = new Uri("https://twitter.com/#!/winsource") };
                webBrowserTask.Show();
            }
            catch
            {
            }
        }

        private void ShowSettings()
        {
            _navigationService.NavigateTo(new Uri("/Views/SettingsPage.xaml", UriKind.Relative));
        }

        private void ShowAbout()
        {
            _navigationService.NavigateTo(new Uri("/Views/AboutPage.xaml", UriKind.Relative));
        }

        private void ReadArticle(Article article)
        {
            CurrentArticle = article;

            ReadCurrentArticle();
        }

        private void ReadCurrentArticle()
        {
            _dataService.ReadArticle(CurrentArticle);

            _navigationService.NavigateTo(new Uri("/Views/ArticlePage.xaml", UriKind.Relative));
        }

        private void ViewCurrentVideo()
        {
            try
            {
                if (CurrentVideo != null)
                {
                    _dataService.ViewVideo(CurrentVideo);

                    WebBrowserTask webBrowserTask = new WebBrowserTask {Uri = new Uri(string.Format("http://www.youtube.com/watch?v={0}", CurrentVideo.Id))};
                    webBrowserTask.Show();
                }
            }
            catch
            {
            }
        }

        private void ShowWriter(Writer writer)
        {
            _navigationService.NavigateTo(new Uri(string.Format("/Views/WritersPage.xaml?Writer={0}", writer.Name), UriKind.Relative));
        }

        private void SendTip()
        {
            try
            {
                EmailComposeTask emailComposeTask = new EmailComposeTask
                {
                    To = "contact@winsource.com",
                    Subject = "News Tip!"
                };
                emailComposeTask.Show();
            }
            catch
            {
            }
        }

        #endregion

        #region Private Methods

        private void UpdateArticles()
        {
            if (_dataService.Articles.Count > 0)
            {
                List<Article> articles = _dataService.Articles;

                FeatureArticle1 = articles[0];
                FeatureArticle2 = articles.Count > 1 ? articles[1] : null;
                FeatureArticle3 = articles.Count > 2 ? articles[2] : null;

                if (_dataService.Articles.Count > 3)
                {
                    List<Article> newArticles = new List<Article>(_dataService.Articles);
                    newArticles.RemoveRange(0, 3);

                    Articles = newArticles;

                    ArticlesByDate = from article in Articles
                                     group article by article.PublishDateDay
                                     into articleByDate orderby articleByDate.Key descending select new GroupArticleByDate(articleByDate.Key, articleByDate);
                }
            }
        }

        private void UpdateVideos()
        {
            Videos = _dataService.Videos;
        }

        #endregion
    }
}